package com.tuuzed.android.dialog;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.res.ResourcesCompat;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public abstract class BaseDialog<ChildBuilder extends BaseDialog.Builder> extends DialogFragment {
    protected LinearLayout mTitleContainer;
    protected ImageView mIvIcon;
    protected TextView mTvTitle;
    protected FrameLayout mContentViewContainer;
    protected LinearLayout mBottomButtonContainer;
    protected TextView mTvPositive;
    protected TextView mTvNeutral;
    protected TextView mTvNegative;
    protected View mSegmentingLine1;
    protected View mSegmentingLine2;

    protected ChildBuilder mParams;

    @Nullable
    protected View mContentView;

    @Override
    public void onStart() {
        super.onStart();
        FragmentActivity activity = getActivity();
        if (activity != null) {
            DisplayMetrics dm = new DisplayMetrics();
            activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
            Window window = getDialog().getWindow();
            if (window != null) {
                window.setLayout(dm.widthPixels, window.getAttributes().height);
            }
        }
    }

    @Nullable
    public View getContentView() {
        return mContentView;
    }

    @Nullable
    protected abstract View onContentView(@NonNull LayoutInflater inflater,
                                          @Nullable ViewGroup container,
                                          @Nullable Bundle savedInstanceState);

    protected void setParams(@NonNull ChildBuilder params) {
        mParams = params;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        // requestHideSystemTitle
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        View root = inflater.inflate(R.layout.base_dialog, container, false);
        // findView
        mTitleContainer = root.findViewById(R.id.title_container);
        mIvIcon = root.findViewById(R.id.iv_icon);
        mTvTitle = root.findViewById(R.id.tv_title);
        mContentViewContainer = root.findViewById(R.id.content_view_container);
        mBottomButtonContainer = root.findViewById(R.id.bottom_button_container);
        mTvPositive = root.findViewById(R.id.tv_positive);
        mTvNeutral = root.findViewById(R.id.tv_neutral);
        mTvNegative = root.findViewById(R.id.tv_negative);
        mSegmentingLine1 = root.findViewById(R.id.segmenting_line_1);
        mSegmentingLine2 = root.findViewById(R.id.segmenting_line_2);
        // initDialog
        setCancelable(mParams.cancelable);
        final Dialog dialog = getDialog();
        if (dialog != null) {
            dialog.setOnShowListener(mParams.showListener);
            dialog.setOnCancelListener(mParams.cancelListener);
            dialog.setOnDismissListener(mParams.dismissListener);
            dialog.setOnKeyListener(mParams.keyListener);
        }
        // initTitle
        if (isShowView(mTitleContainer, mParams.icon != null || mParams.title != null)) {
            if (mParams.titleBackgroundColor != -1) {
                mTitleContainer.setBackgroundColor(mParams.titleBackgroundColor);
            }
            if (isShowView(mIvIcon, mParams.icon != null)) {
                mIvIcon.setImageDrawable(mParams.icon);
            }
            initTextView(mTvTitle, mParams.title, mParams.titleTextColor);
        }
        // initContentView
        mContentView = onContentView(inflater, mContentViewContainer, savedInstanceState);
        if (isShowView(mContentViewContainer, mContentView != null)) {
            mContentViewContainer.removeAllViews();
            mContentViewContainer.addView(mContentView);
        }
        // initBottomButton
        int bottomButtonCount = 0;
        if (initTextView(mTvPositive, mParams.positiveText, mParams.positiveTextColor)) {
            mTvPositive.setOnClickListener(getPositiveClickListener());
            bottomButtonCount++;
        }
        if (initTextView(mTvNeutral, mParams.neutralText, mParams.neutralTextColor)) {
            mTvNeutral.setOnClickListener(getNeutralClickListener());
            bottomButtonCount++;
        }
        if (initTextView(mTvNegative, mParams.negativeText, mParams.negativeTextColor)) {
            mTvNegative.setOnClickListener(getNegativeClickListener());
            bottomButtonCount++;
        }
        if (bottomButtonCount == 3) {
            mSegmentingLine1.setVisibility(View.VISIBLE);
            mSegmentingLine2.setVisibility(View.VISIBLE);
        } else if (bottomButtonCount == 2) {
            mSegmentingLine1.setVisibility(View.VISIBLE);
            mSegmentingLine2.setVisibility(View.GONE);
        } else if (bottomButtonCount == 1) {
            mSegmentingLine1.setVisibility(View.GONE);
            mSegmentingLine2.setVisibility(View.GONE);
        } else {
            mBottomButtonContainer.setVisibility(View.GONE);
        }
        return root;
    }

    protected View.OnClickListener getPositiveClickListener() {
        return v -> {
            if (mParams.positiveClickListener != null) {
                mParams.positiveClickListener.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
            }
        };
    }

    protected View.OnClickListener getNeutralClickListener() {
        return v -> {
            if (mParams.neutralClickListener != null) {
                mParams.neutralClickListener.onClick(getDialog(), DialogInterface.BUTTON_NEGATIVE);
            }
        };
    }

    protected View.OnClickListener getNegativeClickListener() {
        return v -> {
            if (mParams.negativeClickListener != null) {
                mParams.negativeClickListener.onClick(getDialog(), DialogInterface.BUTTON_NEGATIVE);
            }
        };
    }

    private boolean initTextView(@NonNull TextView tv, @Nullable String text, int color) {
        boolean isShow = isShowView(tv, text != null);
        if (isShow) {
            tv.setText(text);
            if (color != -1) tv.setTextColor(color);
        }
        return isShow;
    }

    private boolean isShowView(@NonNull View view, boolean condition) {
        if (condition) {
            view.setVisibility(View.VISIBLE);
        } else {
            view.setVisibility(View.GONE);
        }
        return condition;
    }


    @SuppressWarnings("unchecked")
    public static abstract class Builder<Return extends Builder, Dialog extends BaseDialog> {
        protected Context context;
        // Title
        protected Drawable icon;
        protected String title;
        @ColorInt
        protected int titleTextColor = -1;
        @ColorInt
        protected int titleBackgroundColor = -1;

        // Bottom Button
        protected String negativeText; // 否认的
        @ColorInt
        protected int negativeTextColor = -1;
        protected DialogInterface.OnClickListener negativeClickListener;

        protected String neutralText;  // 中立的
        @ColorInt
        protected int neutralTextColor = -1;
        protected DialogInterface.OnClickListener neutralClickListener;

        protected String positiveText; // 肯定的
        @ColorInt
        protected int positiveTextColor = -1;
        protected DialogInterface.OnClickListener positiveClickListener;

        // Dialog
        protected boolean cancelable = true;
        @Nullable
        protected DialogInterface.OnShowListener showListener;
        @Nullable
        protected DialogInterface.OnCancelListener cancelListener;
        @Nullable
        protected DialogInterface.OnDismissListener dismissListener;
        @Nullable
        protected DialogInterface.OnKeyListener keyListener;

        @SuppressWarnings("WeakerAccess")
        protected Builder(@NonNull Context context) {
            this.context = context;
        }

        public Return icon(@DrawableRes int iconId) {
            return icon(ResourcesCompat.getDrawable(context.getResources(), iconId, context.getTheme()));
        }

        public Return icon(Drawable icon) {
            this.icon = icon;
            return (Return) this;
        }

        public Return title(@StringRes int resId) {
            return title(context.getString(resId));
        }

        public Return title(String title) {
            return title(title, -1);
        }

        public Return title(@StringRes int resId, @ColorInt int textColor) {
            return title(context.getString(resId), textColor);
        }

        public Return title(String title, @ColorInt int textColor) {
            this.title = title;
            this.titleTextColor = textColor;
            return (Return) this;
        }

        public Return titleBackgroundColor(@ColorInt int titleBackgroundColor) {
            this.titleBackgroundColor = titleBackgroundColor;
            return (Return) this;
        }

        public Return negative(@StringRes int resId, DialogInterface.OnClickListener listener) {
            return negative(context.getString(resId), listener);
        }

        public Return negative(String negativeText, DialogInterface.OnClickListener listener) {
            return negative(negativeText, -1, listener);
        }

        public Return negative(@StringRes int resId, @ColorInt int textColor, DialogInterface.OnClickListener listener) {
            return negative(context.getString(resId), textColor, listener);
        }

        public Return negative(String negativeText, int textColor, DialogInterface.OnClickListener listener) {
            this.negativeText = negativeText;
            this.negativeTextColor = textColor;
            this.negativeClickListener = listener;
            return (Return) this;
        }

        public Return neutral(@StringRes int resId, DialogInterface.OnClickListener listener) {
            return neutral(context.getString(resId), listener);
        }

        public Return neutral(String neutralText, DialogInterface.OnClickListener listener) {
            return neutral(neutralText, -1, listener);
        }

        public Return neutral(@StringRes int resId, @ColorInt int textColor, DialogInterface.OnClickListener listener) {
            return neutral(context.getString(resId), textColor, listener);
        }

        public Return neutral(String neutralText, @ColorInt int textColor, DialogInterface.OnClickListener listener) {
            this.neutralText = neutralText;
            this.neutralTextColor = textColor;
            this.neutralClickListener = listener;
            return (Return) this;
        }

        public Return positive(@StringRes int resId, DialogInterface.OnClickListener listener) {
            return positive(context.getString(resId), listener);
        }

        public Return positive(String positiveText, DialogInterface.OnClickListener listener) {
            return positive(positiveText, -1, listener);
        }

        public Return positive(@StringRes int resId, @ColorInt int textColor, DialogInterface.OnClickListener listener) {
            return positive(context.getString(resId), textColor, listener);
        }

        public Return positive(String positiveText, @ColorInt int textColor, DialogInterface.OnClickListener listener) {
            this.positiveText = positiveText;
            this.positiveTextColor = textColor;
            this.positiveClickListener = listener;
            return (Return) this;
        }

        public Return cancelable(boolean cancelable) {
            this.cancelable = cancelable;
            return (Return) this;
        }

        public Return showListener(@Nullable DialogInterface.OnShowListener showListener) {
            this.showListener = showListener;
            return (Return) this;
        }

        public Return cancelListener(@Nullable DialogInterface.OnCancelListener cancelListener) {
            this.cancelListener = cancelListener;
            return (Return) this;
        }

        public Return dismissListener(@Nullable DialogInterface.OnDismissListener dismissListener) {
            this.dismissListener = dismissListener;
            return (Return) this;
        }

        public Return keyListener(@Nullable DialogInterface.OnKeyListener keyListener) {
            this.keyListener = keyListener;
            return (Return) this;
        }

        @NonNull
        public abstract Dialog create();

        @NonNull
        public Dialog show(@NonNull FragmentManager fm) {
            Dialog dialog = create();
            dialog.show(fm, TextUtils.isEmpty(title) ? dialog.getClass().getSimpleName() : title);
            return dialog;
        }

        @NonNull
        public Dialog show(@NonNull FragmentManager fm, @NonNull String tag) {
            Dialog dialog = create();
            dialog.show(fm, tag);
            return dialog;
        }
    }
}
